import 'package:flutter/material.dart';

class MultipleScrollBox extends StatefulWidget {
  const MultipleScrollBox(
      {Key? key, required this.child, required this.scrollCtrl})
      : super(key: key);
  final Widget child;
  final ScrollController scrollCtrl;

  @override
  State<MultipleScrollBox> createState() => _MultipleScrollBoxState();
}

class _MultipleScrollBoxState extends State<MultipleScrollBox> {
  bool _scrolling = false;
  late ScrollController _pageController;

  getMinMaxPosition(double tryScrollTo) {
    return tryScrollTo < _pageController.position.minScrollExtent
        ? _pageController.position.minScrollExtent
        : tryScrollTo > _pageController.position.maxScrollExtent
            ? _pageController.position.maxScrollExtent
            : tryScrollTo;
  }

  @override
  void initState() {
    // TODO: implement initState
    _pageController = widget.scrollCtrl;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return NotificationListener(
        onNotification: (ScrollNotification notification) {
          //users finger is still on the screen
          if (notification is OverscrollNotification &&
              notification.velocity == 0) {
            var scrollTo = getMinMaxPosition(
                _pageController.position.pixels + (notification.overscroll));
            _pageController.jumpTo(scrollTo);
          }
          //users finger left screen before limit of the listview was reached, but momentum takes it to the limit and beoyond
          else if (notification is OverscrollNotification) {
            var yVelocity = notification.velocity;
            _scrolling =
                true; //stops other notifiations overriding this scroll animation
            var scrollTo = getMinMaxPosition(
                _pageController.position.pixels + (yVelocity / 5));
            _pageController
                .animateTo(scrollTo,
                    duration: const Duration(milliseconds: 1000),
                    curve: Curves.linearToEaseOut)
                .then((value) => _scrolling = false);
          }
          //users finger left screen after the limit of teh list view was reached
          else if (notification is ScrollEndNotification &&
              notification.depth > 0 &&
              !_scrolling) {
            var yVelocity =
                notification.dragDetails?.velocity.pixelsPerSecond.dy ?? 0;
            var scrollTo = getMinMaxPosition(
                _pageController.position.pixels - (yVelocity / 5));
            var scrollToPractical =
                scrollTo < _pageController.position.minScrollExtent
                    ? _pageController.position.minScrollExtent
                    : scrollTo > _pageController.position.maxScrollExtent
                        ? _pageController.position.maxScrollExtent
                        : scrollTo;
            _pageController.animateTo(scrollToPractical,
                duration: const Duration(milliseconds: 1000),
                curve: Curves.linearToEaseOut);
          }
          return true;
        },
        child: widget.child);
  }
}
